﻿using CustomCharacter;
using CustomCharacter.Ability;
using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Features;
using Exiled.Events.EventArgs.Interfaces;
using Exiled.Events.EventArgs.Player;
using InventorySystem;
using InventorySystem.Items.Firearms;
using InventorySystem.Items.Firearms.Attachments;
using MEC;
using PlayerRoles;
using PlayerRoles.PlayableScps.Scp939;
using PlayerStatsSystem;
using RgCore.PlayerHud;
using RgCore.API;
using System.Collections.Generic;
using System.Linq;
using CustomCharacter.Interfaces;
using RgCore.CustomSide;
using UnityEngine;
using RgCore.Events;

namespace Scp204
{
    [RoleInfo("SCP-204", RoleTypeId.ClassD, RoleTypeId.Tutorial, MaxHealth = 800)]
    public class Scp204 : CustomCharacter.CustomCharacter, IScpNumber, ICustomSpawnpoint, IRoundStartSpawn, ITrialCard
    {
        public Scp204(int id) : base(id)
        {
        }

        public int Cost => 450;

        private static AbilityOutput Attribute_1(Player player, ref AbilityInfo info, IExiledEvent e, AbilityTrigger trigger)
        {
            var data = info.Datas;
            var protectee = data["protectee"];
            if (trigger == AbilityTrigger.Update)
            {
                if (protectee == null)
                    player.ReferenceHub.playerStats.DealDamage(new CustomReasonDamageHandler("生命衰减", 2.5f));
                return new AbilityOutput(true);
            }
            if (trigger != AbilityTrigger.Event)
            {
                return new AbilityOutput(false);
            }
            if (e is ShootingEventArgs ev7 && ev7.Player == player &&
    player.CurrentItem is Exiled.API.Features.Items.Firearm f && f.Type == ItemType.GunCrossvec)
            {
                f.Ammo = f.MaxAmmo;
                return new AbilityOutput(true);
            }
            if (e is HurtingEventArgs ev8)
            {
                if (ev8.DamageHandler.Base is AttackerDamageHandler && (ev8.Player == player || ev8.Attacker == player) && protectee == null && ev8.Attacker != ev8.Player)
                {
                    ev8.IsAllowed = false;
                    ev8.Amount = 0f;
                }
                if (ev8.Player == protectee && ev8.Amount > 0)
                {
                    ev8.Amount *= 0.5f;
                }
                else if (ev8.DamageHandler.Base is Scp939DamageHandler && ev8.Player == player)
                    ev8.Amount *= 2.5f;
                return new AbilityOutput(true);
            }
            if (e is RemovingHandcuffsEventArgs ev1 && ev1.Player == player && protectee == null)
            {
                ev1.IsAllowed = false;
                return new AbilityOutput(true);
            }
            if (e is UsingItemEventArgs ev2 && ev2.Player == player && protectee == null &&
                (ev2.Item.Category == ItemCategory.Medical || ev2.Item.Type == ItemType.SCP500))
            {
                ev2.IsAllowed = false;
                player.SendRawMsg("denied", "由于技能限制，你不可使用医疗物品", 2, ScreenLocation.CenterBottom, true);
                return new AbilityOutput(true);
            }
            if (e is ActivatingGeneratorEventArgs ev3 && ev3.Player == player && protectee == null)
            {
                ev3.IsAllowed = false;
                player.SendRawMsg("denied", "由于技能限制，你不可激活发电机", 2, ScreenLocation.CenterBottom, true);
                return new AbilityOutput(true);
            }
            if (e is DroppingAmmoEventArgs ev4 && ev4.Player == player && ev4.AmmoType == AmmoType.Nato9)
            {
                ev4.IsAllowed = false;
                player.SendRawMsg("denied", "由于技能限制，你不可丢弃9x19mm子弹", 2, ScreenLocation.CenterBottom, true);
                return new AbilityOutput(true);
            }
            if (e is ChangingRoleEventArgs ev5 && ev5.Player == protectee && ev5.NewRole != RoleTypeId.Spectator)
            {
                RoleTypeId role = RoleTypeId.Tutorial;
                if (ev5.NewRole.GetSide() == Side.Mtf)
                    role = RoleTypeId.NtfSpecialist;
                if (ev5.NewRole.GetSide() == Side.ChaosInsurgency)
                    role = RoleTypeId.ChaosRifleman;
                player.Role.Set(role, SpawnReason.ForceClass, RoleSpawnFlags.None);
                if (role == RoleTypeId.Tutorial)
                {
                    player.SendFormattedMsg("", "SCP-204", "被保护者已死亡", 5, MsgType.Notification, ScreenLocation.CenterTop, true);
                    data["protectee"] = null;
                }
                else
                {
                    player.SendFormattedMsg("", "SCP-204", "你保护的对象角色已发生更改", 5, MsgType.Notification, ScreenLocation.CenterTop, true);
                }
                return new AbilityOutput(true);
            }
            if (e is EnteringPocketDimensionEventArgs ev6 && ev6.Player == player && protectee == null)
            {
                ev6.IsAllowed = false;
            }
            if (e is HandcuffingEventArgs ev9 && (ev9.Target == player || (ev9.Player == player && protectee == null)))
            {
                ev9.IsAllowed = false;
            }
            if (e is DiedEventArgs ev10 && ev10.Player == protectee)
            {
                player.SendFormattedMsg("", "SCP-204", "被保护者已死亡", 5, MsgType.Notification, ScreenLocation.CenterTop, true);
                player.Role.Set(RoleTypeId.Tutorial, SpawnReason.ForceClass, RoleSpawnFlags.None);
                data["protectee"] = null;
            }
            return new AbilityOutput(true);
        }

        public static bool Ability1_Check(Player player, out string response)
        {
            var ab = player.GetAbility("Scp204_Attr_1");
            if (ab.Ability == null)
            {
                response = "此技能需要SCP-204的特性技能才能正常使用";
                return false;
            }
            var data = ab.Datas;
            var _protectee = data["protectee"];
            if (_protectee == null)
            {
                response = "你没有保护者";
                return false;
            }
            Player protectee = _protectee as Player;
            float lost = protectee.MaxHealth - protectee.Health;
            if (lost > player.Health)
            {
                response = "血量低于保护者血量损失量";
                return false;
            }
            response = "";
            return true;
        }

        public static bool Ability2_Check(Player player, out string response)
        {
            var ab = player.GetAbility("Scp204_Attr_1");
            if (ab.Ability == null)
            {
                response = "此技能需要SCP-204的特性技能才能正常使用";
                return false;
            }
            var data = ab.Datas;
            var _protectee = data["protectee"];
            if (_protectee != null)
            {
                response = "你已经有保护对象了";
                return false;
            }
            Player target = player.IsPointingAt(5f);
            if (target == null)
            {
                response = "未选中任何角色（5米内）";
                return false;
            }
            if (target.GetSide() == Side.Scp)
            {
                response = "不可选中SCP玩家";
                return false;
            }
            if (target.GetSide() == Side.None)
            {
                response = "不可选中中立玩家";
                return false;
            }
            if (target.GetSide().Id == "Human")
            {
                response = "不可选中人类阵营玩家（选择CI阵营或MTF玩家？）";
                return false;
            }
            if (target.IsCuffed)
            {
                response = "不可选中被绑玩家";
                return false;
            }
            response = "";
            return true;
        }

        public static AbilityOutput Ability1(Player player, ref AbilityInfo info, IExiledEvent e, AbilityTrigger trigger)
        {
            var ab = player.GetAbility("Scp204_Attr_1");
            if (ab.Ability == null)
                return new AbilityOutput(false, "此技能需要SCP-204的特性技能才能正常使用");
            var data = ab.Datas;
            var _protectee = data["protectee"];
            if (_protectee == null)
                return new AbilityOutput(false, "你没有保护者");
            Player protectee = _protectee as Player;
            float losthp = protectee.MaxHealth - protectee.Health;
            protectee.Health = protectee.MaxHealth;
            protectee.SendRawMsg("", "[<color=#00FFFF>保护你的SCP-204使用了献祭技能，现将他的血量为你补充损失血量</color>]", 2, ScreenLocation.CenterBottom, true);
            player.ReferenceHub.playerStats.DealDamage(new CustomReasonDamageHandler("SCP-204血量献祭") { Damage = losthp });
            return new AbilityOutput(true, $"保护对象已恢复<color=#FFFF00> {losthp} </color>血量");
        }

        public static AbilityOutput Ability2(Player player, ref AbilityInfo info, IExiledEvent e,AbilityTrigger trigger)
        {
            var ab = player.GetAbility("Scp204_Attr_1");
            if (ab.Ability == null)
                return new AbilityOutput(false, "此技能需要SCP-204的特性技能才能正常使用");
            var data = ab.Datas;
            var _protectee = data["protectee"];
            if (_protectee != null)
                return new AbilityOutput(false, "你已经有保护对象了");
            Player target = player.IsPointingAt(5f);
            RoleTypeId role = RoleTypeId.Tutorial;
            switch (target.GetSide().Id)
            {
                case nameof(Side.Mtf):
                    {
                        role = RoleTypeId.NtfSpecialist;
                        break;
                    }
                case nameof(Side.ChaosInsurgency):
                    {
                        role = RoleTypeId.ChaosConscript;
                        break;
                    }
                default:
                    {
                        return new AbilityOutput(false, "此角色不可用");
                    }
            }
            player.Role.Set(role, SpawnReason.ForceClass, RoleSpawnFlags.None);
            data["protectee"] = target;
            target.SendRawMsg("", $"你受到SCP-204: <color=#FFFF00>{player.Nickname}</color> 的保护（50%免伤）", 5, ScreenLocation.CenterBottom, true);
            Timing.CallDelayed(1f, () =>
            {
                player.Position = target.Position;
            });
            return new AbilityOutput(true, $"已将<color=#00FF00> {target.Nickname} </color>作为你的保护对象");
        }

        public Player Protectee { get; protected set; } = null;

        public override IEnumerable<Ability> AbilityRegister()
        {
            return new Ability[]
            {
                new Ability("Scp204_1",
                "立刻回满保护者的血量，同时扣除自身相应的治疗量", AbilityType.Offensive, 60, Ability1, Ability1_Check, null, null, GetType()),
                new Ability("Scp204_2", "将看向的目标作为自己的保护目标。",
                AbilityType.Offensive, 30, Ability2, Ability2_Check, null, null, GetType()),
                new AttributeAbility("Scp204_Attr_1", "Vector无限弹药；保护者50%免伤", Attribute_1,
                true, new IExiledEvent[] {
                    Exiled.Events.Handlers.Player.Handcuffing,
                    Exiled.Events.Handlers.Player.RemovingHandcuffs,
                    Exiled.Events.Handlers.Player.Died,
                    Exiled.Events.Handlers.Player.Shooting,
                    EventProcessor.OnHurting,
                    Exiled.Events.Handlers.Player.EnteringPocketDimension,
                    Exiled.Events.Handlers.Player.ChangingRole,
                    Exiled.Events.Handlers.Player.DroppingAmmo,
                    Exiled.Events.Handlers.Player.ActivatingGenerator,
                    Exiled.Events.Handlers.Player.UsingItem
                }, new KeyValuePair<string, object>[]
                {
                    new KeyValuePair<string, object>("protectee", null)
                }, GetType())
            };
        }

        public override void Role_Activate()
        {
            base.Role_Activate();
            Timing.CallDelayed(1f, () =>
            {
                Player.Position = Room.List.Where(x => x.Type == RoomType.EzTCross).First().Position + Vector3.up * 1.5f;
                var firearm = (InventorySystem.Items.Firearms.Firearm)Player.Inventory.ServerAddItem(ItemType.GunCrossvec);
                if (AttachmentsServerHandler.PlayerPreferences.TryGetValue(Player.ReferenceHub, out Dictionary<ItemType, uint> dictionary) && dictionary.TryGetValue(firearm.ItemTypeId, out uint code))
                {
                    firearm.ApplyAttachmentsCode(code, true);
                }
                FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted;
                if (firearm.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight))
                {
                    firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled;
                }
                firearm.Status = new FirearmStatus(firearm.AmmoManagerModule.MaxAmmo, firearmStatusFlags, firearm.GetCurrentAttachmentsCode());
                Player.AddItem(ItemType.KeycardGuard);
                Player.AddAmmo(AmmoType.Nato9, 100);
            });
        }

        public override void Role_Deactive()
        {
            base.Role_Deactive();
            Protectee?.SendRawMsg("", "<color=red>警告</color>:保护你的SCP-204已经死亡，你的减伤效果已消失", 3, ScreenLocation.CenterBottom, true); ;
        }

        public override Color32 RoleColor => new Color32(138, 43, 226, 255);

        public string ScpNumber => "204";

        public Vector3 SpawnPosition => RoleExtensions.GetRandomSpawnLocation(PlayerRoles.RoleTypeId.FacilityGuard).Position;

        public byte MinPlayers => 12;
    }
}